﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hrm.Core;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using System.Web;
using Microsoft.AspNet.Identity;

namespace Hrm.Services
{
    public class ResourceService : BaseService<Resource>, IResourceService
    {
        IResourcePermissionDbRepository _resourcePermissionDbRepository;
        IPermissionPermissionDbRepository _permissionPermissionDbRepository;
        IResourceAndPermissionPermissionDbRepository _resourceAndPermissionPermissionDbRepository;
        IDictionaryService _dictionaryService;
        public ResourceService(IResourcePermissionDbRepository resourcePermissionDbRepository, IPermissionPermissionDbRepository permissionPermissionDbRepository, IResourceAndPermissionPermissionDbRepository resourceAndPermissionPermissionDbRepository, IDictionaryService dictionaryService)
            : base(resourcePermissionDbRepository)
        {
            this._resourcePermissionDbRepository = resourcePermissionDbRepository;
            this._permissionPermissionDbRepository = permissionPermissionDbRepository;
            this._resourceAndPermissionPermissionDbRepository = resourceAndPermissionPermissionDbRepository;
            this._dictionaryService = dictionaryService;
        }


        public PageResponse<ResourceDto> GetPageList(PageRequest<ResourceDto> request)
        {
            var query = this.GetAllAbledAndOrderByCreatetime();
            if (!string.IsNullOrEmpty(request.filter.Name))
            {
                query = query.Where(p => p.Name.Contains(request.filter.Name));
            }
            if (!string.IsNullOrEmpty(request.filter.Type))
            {
                query = query.Where(p => p.Type == request.filter.Type);
            }
            var data = query.Project().To<ResourceDto>();
            if (request.filter.ApplicationId > 0)
            {
                data = data.Where(p => p.ApplicationId == request.filter.ApplicationId);
            }
            PageResponse<ResourceDto> result = new PageResponse<ResourceDto>(data, request.draw, request.start, request.length);
            var tempRourseType = this._dictionaryService.GetDictionaryByType(Constant.DictionaryRourseType);
            foreach (var item in result.data)
            {
                item.TypeName = tempRourseType.FirstOrDefault(p => p.Code == item.Type) == null ? "" : tempRourseType.FirstOrDefault(p => p.Code == item.Type).Name;
            }
            return result;
        }

        public IEnumerable<ResourceShowDto> GetResourceToShow(int appId, string type, List<string> roleCodes)
        {
            IEnumerable<Resource> rsources = this._resourcePermissionDbRepository.GetList(p => p.Application.Id == appId && p.Type == type &&
                (roleCodes.Contains(Constant.AdministratorRoleCode) || p.ResourceAndPermissions.Any(x => x.Roles.Any(y => roleCodes.Contains(y.Code)))) &&
                p.IsEnable != false).OrderBy(p => p.Order).ToList();
            IEnumerable<ResourceShowDto> result = AddSubNav(Constant.ResourceParentCodeMenuRoot, rsources);
            return result;
        }

        private IEnumerable<ResourceShowDto> AddSubNav(string parentCode, IEnumerable<Resource> resources)
        {
            List<ResourceShowDto> result = new List<ResourceShowDto>();
            List<Resource> rootNavs = resources.Where(p => p.ParentCode == parentCode).ToList();
            foreach (var item in rootNavs)
            {
                result.Add(new ResourceShowDto
                {
                    Code = item.Code,
                    Name = item.Name,
                    Url = item.Url,
                    GlyphiconsClass = item.GlyphiconsClass,
                    Children = AddSubNav(item.Code, resources)
                });
            }
            return result;
        }


        public ResponseModel EditPermissionSubmit(EditPermissionDto request)
        {
            ResponseModel result = new ResponseModel();
            var model = this._resourcePermissionDbRepository.GetById(request.ResourceId);
            var PermissiionIds = request.PermissiionIds ?? new List<int>();
            var SelectPermissiionIds = request.SelectPermissiionIds ?? new List<int>();
            var deletePermissiionIds = PermissiionIds.Where(p => !SelectPermissiionIds.Contains(p));
            var addPermissiionIds = SelectPermissiionIds.Where(p => !PermissiionIds.Contains(p));
            try
            {
                if (deletePermissiionIds.Count() > 0)
                {
                    var deletePermissions = model.ResourceAndPermissions.Where(p => deletePermissiionIds.Contains(p.Permission.Id)).Select(p => p).ToList();
                    if (deletePermissions != null && deletePermissions.Count() > 0)
                        deletePermissions.ForEach(p => this._resourceAndPermissionPermissionDbRepository.Delete(p));
                }
                foreach (var item in addPermissiionIds)
                {
                    var tempResourceModel = this._permissionPermissionDbRepository.GetById(item);
                    if (tempResourceModel != null)
                    {
                        ResourceAndPermission tempModel = new ResourceAndPermission();
                        tempModel.Resource = model;
                        tempModel.Permission = tempResourceModel;
                        if (HttpContext.Current.User != null)
                        {
                            tempModel.CreateDatetime = DateTime.Now;
                            tempModel.CreateUserCode = HttpContext.Current.User.Identity.GetUserId();
                        }
                        if (model.ResourceAndPermissions == null)
                        {
                            model.ResourceAndPermissions = new List<ResourceAndPermission>();
                        }
                        model.ResourceAndPermissions.Add(tempModel);
                    }
                }
                this.Update(model);
            }
            catch (Exception ex)
            {
                result.SetFailed("操作失败：" + ex.Message);
            }
            return result;
        }
    }
}
